package com.lzx.spring3.aop;

import java.lang.reflect.Method;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint;
import org.springframework.stereotype.Component;

import com.lzx.spring3.annotation.Cache;
import com.lzx.spring3.annotation.User;

/**
 * AOP
 * 
 * @author nassir wen
 */
@Aspect
@Component
public class Aop {
	private final static Log logger = LogFactory.getLog(Aop.class);

	/**
	 * 定义一个切入点,在方法含@Anno注解位置切入
	 */
	// @Pointcut("@annotation(com.lzx.spring3.annotation.Cache)")
	// @Pointcut("* com.lzx.spring3.dao..*.*())")
	@Pointcut("execution(* com.lzx.spring3.dao.impl.*.*(..))")
	// execution(public * com. savage.service.UserService.*(..))
	public void aopPoint() {
	}

	/**
	 * @param jp
	 * @return
	 */
	@Around("aopPoint()")
	public Object execAop(ProceedingJoinPoint pjp) throws Throwable {
//		System.out.println(pjp.getThis().getClass().getName());
//		System.out.println(pjp.getTarget().getClass().getName());
//		for (Method m : pjp.getTarget().getClass().getMethods()) {
//			System.out.println("target:" + m.getName() + "(" + getParameterTypes(m)  +")");
		
		
//		}
		

		Method method = getMethod(pjp);
		
		MethodInvocationProceedingJoinPoint methodInvocationProceedingJoinPoint = null;
		
		
		
		
		Cache c = pjp.getSignature().getClass().getAnnotation(Cache.class);
		System.out.println("proxy:" + method.getName() + "(" + getParameterTypes(method)  +")");
		Cache cache = method.getAnnotation(Cache.class);
		if (cache == null) {
			cache = pjp.getTarget().getClass()
					.getMethod(method.getName(), method.getParameterTypes())
					.getAnnotation(Cache.class);
		}
		//
		String methodName = method.getName();
		System.out.println(methodName + "@Cache:" + cache);
		System.out.println(methodName + "(" + getParameterTypes(method) + ")");
		// if (methodName.startsWith("get")) {
		//
		// }

		return pjp.proceed();
	}

	private Method getMethod(JoinPoint jp) throws NoSuchMethodException {
		Signature sig = jp.getSignature();
		MethodSignature msig = (MethodSignature) sig;
		return getClass(jp).getMethod(msig.getName(), msig.getParameterTypes());
	}

	private Class<? extends Object> getClass(JoinPoint jp)
			throws NoSuchMethodException {
		return jp.getTarget().getClass();
	}

	public static String getParameterTypes(Method method) {
		StringBuilder sb = new StringBuilder();
		for (Class clz : method.getParameterTypes()) {
			sb.append(clz.getSimpleName() + ",");
		}
		return sb.toString();

	}
}